/**
 * \file talise_rx.c
 * \brief Contains functions to support Talise Rx and Observation Rx data path
 *        control
 *
 * Talise API version: 3.6.0.5
 *
 * Copyright 2015-2017 Analog Devices Inc.
 * Released under the AD9378-AD9379 API license, for more information see the "LICENSE.txt" file in this zip file.
 */

#include "talise_rx.h"
#include "talise_gpio.h"
#include "talise_reg_addr_macros.h"
#include "talise_arm_macros.h"
#include "talise_hal.h"
#include "talise_user.h"
#include "talise_error.h"
#include "talise.h"
#include "talise_gpio.h"

uint32_t TALISE_programRxGainTable(taliseDevice_t *device, taliseRxGainTable_t *gainTablePtr, uint8_t numGainIndexesInTable, taliseRxChannels_t rxChannel)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t tableRowIndex = 0;
    uint8_t ctlReg = 0;
    uint8_t i = 0;
    uint32_t addrIndex = 0;
    uint32_t spiBufferSize = (((HAL_SPIWRITEARRAY_BUFFERSIZE / 8) - 1) * 8);
    uint16_t addrArray[HAL_SPIWRITEARRAY_BUFFERSIZE] = {0};
    uint8_t dataArray[HAL_SPIWRITEARRAY_BUFFERSIZE] = {0};
    static const uint8_t EN_TABLECLK = 0x05;
    uint8_t digGainSign = 0;
    uint16_t digGainMag = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_programRxGainTable()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if ((rxChannel == TAL_RX1) ||
        (rxChannel == TAL_RX2) ||
        (rxChannel == TAL_RX1RX2))
    {
        /* Verify Rx profile is valid before allowing to set the Rx gain table, this
         * ensures the device->rx structure pointers are valid
         */
        if ((device->devStateInfo.profilesValid  & RX_PROFILE_VALID) == 0)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_RXGAINTABLE_INV_PROFILE, retVal, TALACT_ERR_CHECK_PARAM);
        }

        /* Check for proper mapping for gain table and passed table number of indexes */
        if (numGainIndexesInTable > ((START_RX_GAIN_INDEX - MIN_RX_GAIN_TABLE_INDEX) + 1))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_RXGAINTABLE_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (gainTablePtr == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check for channel and the logic behind it */
    if ((rxChannel == TAL_RX1) ||
        (rxChannel == TAL_RX1RX2))
    {
        /* normalize min/max index in device structure to 255 index = max gain */
        device->devStateInfo.gainIndexes.rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX;
        device->devStateInfo.gainIndexes.rx1MinGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1;
    }

    if ((rxChannel == TAL_RX2) ||
        (rxChannel == TAL_RX1RX2))
    {
        /* normalize min/max index in device structure to 255 index = max gain */
        device->devStateInfo.gainIndexes.rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX;
        device->devStateInfo.gainIndexes.rx2MinGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1;
    }

    /* starting the gain table clock and read from gain table address bits */
    ctlReg = (uint8_t)((rxChannel << 3) | EN_TABLECLK);
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* programming a table selected by rxChannel enum type */
    addrIndex = 0;

    for(i = START_RX_GAIN_INDEX; i > START_RX_GAIN_INDEX - numGainIndexesInTable; i--)
    {
        tableRowIndex = START_RX_GAIN_INDEX - i;

        /* set current gain table index (address) */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_ADDRESS;
        dataArray[addrIndex++] = i;

        /* Set Rx Front End gain[7:0] */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_RXFE;
        dataArray[addrIndex++] = gainTablePtr[tableRowIndex].rxFeGain;

        /* Set external control [3:0] */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_EXT;
        dataArray[addrIndex++] = gainTablePtr[tableRowIndex].extControl;

        digGainSign = (gainTablePtr[tableRowIndex].digGain < 0) ? 1 : 0;
        digGainMag = (uint16_t)((digGainSign > 0) ? (-gainTablePtr[tableRowIndex].digGain) : gainTablePtr[tableRowIndex].digGain);

        /* Set digital attenuation/gain[10:4] */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_DIG;
        dataArray[addrIndex++] = ((digGainSign & 0x01) << 6) | (((uint8_t)(digGainMag >> 4 )) & 0x3F);

        /* Set digital attenuation/gain[3:0], TIA control */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_DIG2;
        dataArray[addrIndex++] = ((gainTablePtr[tableRowIndex].adcTiaGain & 0x03) << 4) | ((uint8_t)(digGainMag & 0x0F));

        /* Set Phase offset if Rx gain table */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_PHASE_OFFSET;
        dataArray[addrIndex++] = (uint8_t)(gainTablePtr[tableRowIndex].phaseOffset & 0xFF);

        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_PHASE_OFFSET2;
        dataArray[addrIndex++] = (uint8_t)((gainTablePtr[tableRowIndex].phaseOffset >> 8) & 0xFF);

        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_CONFIGURATION;
        dataArray[addrIndex++] = (ctlReg | 0x02);

        if (addrIndex >= spiBufferSize)
        {
            halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], addrIndex);
            retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);

            addrIndex = 0;
        }
    }

    if (addrIndex > 0)
    {
        halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], addrIndex);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    /* disabling the gain table clock */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_programOrxGainTable(taliseDevice_t *device, taliseOrxGainTable_t *gainTablePtr, uint8_t numGainIndexesInTable, taliseObsRxChannels_t orxChannel)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t tableRowIndex = 0;
    uint8_t ctlReg = 0;
    uint8_t i = 0;
    uint32_t addrIndex = 0;
    uint32_t spiBufferSize = (((HAL_SPIWRITEARRAY_BUFFERSIZE / 6) - 1) * 6);
    uint16_t addrArray[HAL_SPIWRITEARRAY_BUFFERSIZE] = {0};
    uint8_t dataArray[HAL_SPIWRITEARRAY_BUFFERSIZE] = {0};
    static const uint8_t EN_TABLECLK = 0x05;
    uint8_t digGainSign = 0;
    uint16_t digGainMag = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_programOrxGainTable()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if ((orxChannel == TAL_ORX1) ||
        (orxChannel == TAL_ORX2) ||
        (orxChannel == TAL_ORX1ORX2))
    {
        /* Verify ORx profile is valid before allowing to set the ORx gain table, this
         * ensures the device->obsRx structure pointers are valid
         */
        if ((device->devStateInfo.profilesValid  & ORX_PROFILE_VALID) == 0)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_ORXGAINTABLE_INV_PROFILE, retVal, TALACT_ERR_CHECK_PARAM);
        }

        /* Check for proper mapping for gain table and passed table number of indexes */
        if (numGainIndexesInTable > ((START_ORX_GAIN_INDEX -  MIN_ORX_GAIN_TABLE_INDEX) + 1))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_ORXGAINTABLE_INV_GAIN_INDEX_RANGE, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_ORXGAINTABLE_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (gainTablePtr == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_PROGRAM_ORXGAIN_TABLE_NULL_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check for channel and the logic behind it */
    if ((orxChannel == TAL_ORX1) ||
        (orxChannel == TAL_ORX1ORX2))
    {
        /* normalize min/max index in device structure to 255 index = max gain */
        device->devStateInfo.gainIndexes.orx1MaxGainIndex = MAX_GAIN_TABLE_INDEX;
        device->devStateInfo.gainIndexes.orx1MinGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1;
    }

    if ((orxChannel == TAL_ORX2) ||
        (orxChannel == TAL_ORX1ORX2))
    {
        /* normalize min/max index in device structure to 255 index = max gain */
        device->devStateInfo.gainIndexes.orx2MaxGainIndex = MAX_GAIN_TABLE_INDEX;
        device->devStateInfo.gainIndexes.orx2MinGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1;
    }

    /* starting the gain table clock and read from gain table address bits */
    ctlReg = (uint8_t)((orxChannel << 3) | EN_TABLECLK);
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* programming a table selected by rxChannel enum type */
    addrIndex = 0;

    for(i = START_ORX_GAIN_INDEX; i > START_ORX_GAIN_INDEX - numGainIndexesInTable; i--)
    {
        tableRowIndex = START_ORX_GAIN_INDEX - i;

        /* set current gain table index (address) */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_ADDRESS;
        dataArray[addrIndex++] = i;

        /* Set Rx Front End gain[7:0] */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_RXFE;
        dataArray[addrIndex++] = gainTablePtr[tableRowIndex].rxFeGain;

        /* Set external control [3:0] */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_EXT;
        dataArray[addrIndex++] = gainTablePtr[tableRowIndex].extControl;

        digGainSign = (gainTablePtr[tableRowIndex].digGain < 0) ? 1 : 0;
        digGainMag = (uint16_t)((digGainSign > 0) ? (-gainTablePtr[tableRowIndex].digGain) : gainTablePtr[tableRowIndex].digGain);

        /* Set digital attenuation/gain[10:4] */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_DIG;
        dataArray[addrIndex++] = ((digGainSign & 0x01) << 6) | (((uint8_t)(digGainMag >> 4 )) & 0x3F);

        /* Set digital attenuation/gain[3:0], TIA control */
        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_WORD_DATA_DIG2;
        dataArray[addrIndex++] = ((gainTablePtr[tableRowIndex].adcTiaGain & 0x03) << 4) | ((uint8_t)(digGainMag & 0x0F));

        addrArray[addrIndex] = TALISE_ADDR_GAIN_TABLE_CONFIGURATION;
        dataArray[addrIndex++] = (ctlReg | 0x02);

        if (addrIndex >= spiBufferSize)
        {
            halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], addrIndex);
            retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);

            addrIndex = 0;
        }
    }

    if (addrIndex > 0)
    {
        halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], addrIndex);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    /* disabling the gain table clock */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_setRxManualGain(taliseDevice_t *device, taliseRxChannels_t rxChannel, uint8_t gainIndex)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setRxManualGain()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* Verify Rx profile is valid */
    if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) == 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXGAIN_RXPROFILE_INVALID, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxChannel == TAL_RX1)
    {
        if ((gainIndex < device->devStateInfo.gainIndexes.rx1MinGainIndex) ||
            (gainIndex > device->devStateInfo.gainIndexes.rx1MaxGainIndex))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRX1GAIN_INV_GAIN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MANUAL_GAIN_INDEX_RX1, (START_RX_GAIN_INDEX - (MAX_GAIN_TABLE_INDEX - gainIndex)));
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }
    else if (rxChannel == TAL_RX2)
    {
        if ((gainIndex < device->devStateInfo.gainIndexes.rx2MinGainIndex) ||
            (gainIndex > device->devStateInfo.gainIndexes.rx2MaxGainIndex))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRX2GAIN_INV_GAIN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MANUAL_GAIN_INDEX_RX2, (START_RX_GAIN_INDEX - (MAX_GAIN_TABLE_INDEX - gainIndex)));
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXGAIN_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_getRxGain(taliseDevice_t *device, taliseRxChannels_t rxChannel, uint8_t *rxGainIndex)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t readData = 0;
    uint16_t regGainCh = TALISE_ADDR_RX1_GAIN_INDEX;
    uint8_t channelMaxGainIndex = START_RX_GAIN_INDEX;
    uint8_t channelMinGainIndex = MIN_RX_GAIN_TABLE_INDEX;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getRxGain()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) == 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETRXGAIN_INV_RXPROFILE, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxChannel == TAL_RX1)
    {
        regGainCh = TALISE_ADDR_RX1_GAIN_INDEX;
    }
    else if (rxChannel == TAL_RX2)
    {
        regGainCh = TALISE_ADDR_RX2_GAIN_INDEX;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETRXGAIN_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Write the readback register to update the value */
    halError = talSpiWriteByte(device->devHalInfo, regGainCh, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* read back the current gain index for the required channel */
    halError = talSpiReadByte(device->devHalInfo, regGainCh, &readData);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* range check the gain against the max and min expected values */
    if ((readData > channelMaxGainIndex) ||
        (readData < channelMinGainIndex))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETRXGAIN_GAIN_RANGE_EXCEEDED, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* normalize channel's gain index to 255 max gain index */
    readData = (MAX_GAIN_TABLE_INDEX - (channelMaxGainIndex - readData));

    if (rxGainIndex != NULL)
    {
        *rxGainIndex = readData;
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_setObsRxManualGain(taliseDevice_t *device, taliseObsRxChannels_t obsRxCh, uint8_t gainIndex)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t manualGainIndexSpiAddr = 0;
    uint8_t orxGainIndex = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setObsRxManualGain()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* Verify ORx profile is valid, also verifies device data struct pointers
     * used below are valid
     */
    if ((device->devStateInfo.profilesValid & ORX_PROFILE_VALID) == 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETORXGAIN_INV_ORXPROFILE, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* check for valid channel and assign address */
    switch(obsRxCh)
    {
        case TAL_ORX1:
            if ((gainIndex < device->devStateInfo.gainIndexes.orx1MinGainIndex) ||
                (gainIndex > device->devStateInfo.gainIndexes.orx1MaxGainIndex))
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETORXGAIN_INV_ORX1GAIN, retVal, TALACT_ERR_CHECK_PARAM);
            }

            /* GainIndex in data struct is normalized to 255 = max gain index */
            orxGainIndex = (START_ORX_GAIN_INDEX - (MAX_GAIN_TABLE_INDEX - gainIndex));
            manualGainIndexSpiAddr = TALISE_ADDR_MANUAL_GAIN_INDEX_ORX_RX1;
            break;

        case TAL_ORX2:
            if ((gainIndex < device->devStateInfo.gainIndexes.orx2MinGainIndex) ||
                (gainIndex > device->devStateInfo.gainIndexes.orx2MaxGainIndex))
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETORXGAIN_INV_ORX2GAIN, retVal, TALACT_ERR_CHECK_PARAM);
            }

            /* GainIndex in data struct is normalized to 255 = max gain index */
            orxGainIndex = (START_ORX_GAIN_INDEX - (MAX_GAIN_TABLE_INDEX - gainIndex));
            manualGainIndexSpiAddr = TALISE_ADDR_MANUAL_GAIN_INDEX_ORX_RX2;
            break;

        default:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETORXGAIN_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);

    }

    /* update the value in the device data structure, and write to device.*/
    halError = talSpiWriteByte(device->devHalInfo, manualGainIndexSpiAddr, orxGainIndex);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_getObsRxGain(taliseDevice_t *device, taliseObsRxChannels_t obsRxChannel, uint8_t *obsRxGainIndex)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t readData = 0;
    uint16_t regGainCh = TALISE_ADDR_ORX1_GAIN_INDEX;
    uint8_t channelMaxGainIndex = START_ORX_GAIN_INDEX;
    uint8_t channelMinGainIndex = MIN_ORX_GAIN_TABLE_INDEX;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getObsRxGain()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if ((device->devStateInfo.profilesValid & ORX_PROFILE_VALID) == 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETOBSRXGAIN_INV_ORXPROFILE, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (obsRxChannel == TAL_ORX1)
    {
        regGainCh = TALISE_ADDR_ORX1_GAIN_INDEX;
    }
    else if (obsRxChannel == TAL_ORX2)
    {
        regGainCh = TALISE_ADDR_ORX2_GAIN_INDEX;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETOBSRXGAIN_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Write the readback register to update the value */
    halError = talSpiWriteByte(device->devHalInfo, regGainCh, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* read back the current gain index for the required channel */
    halError = talSpiReadByte(device->devHalInfo, regGainCh, &readData);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* range check the gain against the max and min expected values */
    if ((readData > channelMaxGainIndex) ||
        (readData < channelMinGainIndex))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETOBSRXGAIN_GAIN_RANGE_EXCEEDED, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* normalize channel's gain index to 255 max gain index */
    readData = (MAX_GAIN_TABLE_INDEX - (channelMaxGainIndex - readData));

    if (obsRxGainIndex != NULL)
    {
        *obsRxGainIndex = readData;
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_setRxGainControlMode(taliseDevice_t *device, taliseGainMode_t mode)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    static const uint8_t rxGainTypeBitMask = 0x03;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setRxGainControlMode()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* performing AGC type check */
    switch (mode)
    {
        case TAL_MGC:
            break;
        case TAL_AGCSLOW:
             break;
        case TAL_AGCFAST: /* Fall through to next case */
        case TAL_HYBRID:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_UNSUPPORTED_RX_GAIN_MODE_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        default:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_INV_RX_GAIN_MODE_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* read, modify, write AGC type for Rx1 */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_CONFIG_RX1, (uint8_t)mode, rxGainTypeBitMask, 0);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* read, modify, write AGC type for Rx2 */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_CONFIG_RX2, (uint8_t)mode, rxGainTypeBitMask, 0);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* writing mode setting to device state information container */
    device->devStateInfo.gainMode = mode;

    return (uint32_t)retVal;
}

uint32_t TALISE_setRxDataFormat (taliseDevice_t *device, taliseRxDataFormat_t *rxDataFormat)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

    uint8_t fpConfig = 0;
    uint8_t fpAtten = 0;
    uint8_t gainConfig = 0;
    uint8_t intConfig = 0;
    uint8_t slicerConfig = 0;
    uint8_t rx1GpioSelect = 0;
    uint8_t rx2GpioSelect = 0;
    uint8_t rx1Gpio = 0;
    uint8_t rx2Gpio = 0;
    uint8_t rx1SendGpio = 0;
    uint8_t rx2SendGpio = 0;
    uint8_t dualConfig = 0;
    uint8_t dualModeBit = 0;
    uint8_t combineDualband = 0;
    uint32_t srcCntrl = 0;
    uint32_t gpioAssignMask = 0;
    uint32_t gpioFreeMask = 0;
    uint32_t npCheck = 0;

    taliseRx1ExtSlicerGpioSelect_t rx1GpioConfig = TAL_EXTSLICER_RX1_GPIO_DISABLE;
    taliseRx2ExtSlicerGpioSelect_t rx2GpioConfig = TAL_EXTSLICER_RX2_GPIO_DISABLE;

    static const uint8_t rxChannelMask = 0x03;
    static const uint8_t GAIN_COMP_EN_BITM = 0x01;
    static const uint8_t PIN_CONTROL_BITM = 0x20;
    static const uint8_t SLICER_NUMBERBITS_BITM = 0x20;
    static const uint8_t SLICER_BIT_POSITION_BITM = 0x10;
    static const uint8_t SLICER_EMBED_EN_BITM = 0x08;
    static const uint8_t DATA_RESOLUTION_BITM = 0x06;
    static const uint8_t DATA_RESOLUTION_16BIT = 0x02;
    static const uint8_t DATA_RESOLUTION_24BIT = 0x04;
    static const uint8_t SIGNED_MAGNITUDE_BITM = 0x01;
    static const uint32_t GPIO0_1_2_BITM = 0x00000007;
    static const uint32_t GPIO5_6_7_BITM = 0x000000E0;
    static const uint32_t GPIO8_9_10_BITM = 0x00000700;
    static const uint32_t GPIO11_12_13_BITM = 0x00003800;
    static const uint32_t GPIO12_13_14_BITM = 0x00007000;
    static const uint32_t GPIO_OE_BITM = 0x7FFFF;
    static const uint32_t INTSLICER_NIBBLE_SOURCE = ((((uint32_t)TAL_GPIO_SLICER_OUT_MODE) << 12) | (((uint32_t)TAL_GPIO_SLICER_OUT_MODE) << 8));
    static const uint32_t INTSLICER_NIBBLE_CLEAR_BITM = 0xFFFF00FF;
    static const uint8_t DUALBANDENABLE = 1;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setRxDataFormat()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* Range check the configuration structure */
    if (rxDataFormat == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->formatSelect > TAL_GAIN_WITH_EXTERNAL_SLICER)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_FORMATSELECT_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->tempCompensationEnable > 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_TEMPCOMP_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->intEmbeddedBits > TAL_EMBED_2_SLICERBITS_AT_LSB)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_INTEMBEDDEDBITS_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->intSampleResolution > TAL_INTEGER_24BIT_SIGNED)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_INTSAMPLERESOLUTION_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->extPinStepSize > TAL_EXTSLICER_STEPSIZE_4DB)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_PINSTEPSIZE_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->rx1GpioSelect > TAL_EXTSLICER_RX1_GPIO_DISABLE)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_RX1GPIOSELECT_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((rxDataFormat->rx2GpioSelect != TAL_EXTSLICER_RX2_GPIO11_12_13) &&
        (rxDataFormat->rx2GpioSelect != TAL_EXTSLICER_RX2_GPIO5_6_7) &&
        (rxDataFormat->rx2GpioSelect != TAL_EXTSLICER_RX2_GPIO_DISABLE))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_RX2GPIOSELECT_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxDataFormat->externalLnaGain > 1)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SET_RXDATAFRMT_EXTERNALLNAGAIN_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Calculate dualBandMode settings */
    if (device->devStateInfo.rxDualBandEnabled == DUALBANDENABLE)
    {

        /* if single Rx channel enabled then combine bands if M=2, separate bands if M=4 */
        if (((device->devStateInfo.initializedChannels & rxChannelMask) == 1) ||
            ((device->devStateInfo.initializedChannels & rxChannelMask) == 2))
        {
            combineDualband = (device->devStateInfo.rxTotalM == 2) ? 1 : 0;
        }

        /* if both Rx channels enabled then combine if M=4, separate if M=8 */
        else if ((device->devStateInfo.initializedChannels & rxChannelMask) == 3)
        {
            combineDualband = (device->devStateInfo.rxTotalM == 4) ? 1 : 0;
        }

        /* throw an error if no Rx channel enabled */
        else
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SET_RXDATAFRMT_RXCHAN_DISABLED, retVal, TALACT_ERR_CHECK_PARAM);
        }

        /* For floating point dualmode is set if combineDualband is set, cleared if combineDualband is clear */
        if (rxDataFormat->formatSelect == TAL_GAIN_WITH_FLOATING_POINT)
        {
            dualModeBit = combineDualband;
        }
        /* for internal slicer dualmode is set if no embedded bits, set if bits are embedded and combineDualband is set */
        else if ((rxDataFormat->formatSelect == TAL_GAIN_WITH_INTSLICER) ||
                 (rxDataFormat->formatSelect == TAL_GAIN_WITH_INTSLICER_NOGPIO))
        {
            if (rxDataFormat->intEmbeddedBits ==  TAL_NO_EMBEDDED_SLICER_BITS)
            {
                dualModeBit = 1;
            }
            else
            {
                dualModeBit = combineDualband;
            }
        }
        /* for external slicer dualMode is always cleared */
        else
        {
            dualModeBit = 0;
        }
     }
    /* dualMode is cleared for TAL_RXDDC_DEC2 not selected */
    else
    {
        dualModeBit = 0;
    }

    dualConfig = (dualModeBit << 2) | ((rxDataFormat->externalLnaGain << 1) | (rxDataFormat->tempCompensationEnable));

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_COMPENSATION_AND_SLICER_CONFIG2, dualConfig);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* read the Rx1 gpio config */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_RX1_SLICER_GPIO_CONFIG, &rx1SendGpio);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);
    rx1GpioConfig = (taliseRx1ExtSlicerGpioSelect_t)rx1SendGpio;

    /* deassign any rx1 gpios already in use */
    if (rx1GpioConfig == TAL_EXTSLICER_RX1_GPIO0_1_2)
    {
        gpioFreeMask = GPIO0_1_2_BITM;
    }
    else if (rx1GpioConfig == TAL_EXTSLICER_RX1_GPIO5_6_7)
    {
        gpioFreeMask = GPIO5_6_7_BITM;
    }
    else if (rx1GpioConfig == TAL_EXTSLICER_RX1_GPIO8_9_10)
    {
        gpioFreeMask = GPIO8_9_10_BITM;
    }
    else
    {
        gpioFreeMask = 0;
    }

    /* free the unused GPIOs */
    retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, (~gpioFreeMask & GPIO_OE_BITM),  gpioFreeMask);
    IF_ERR_RETURN_U32(retVal);
    device->devStateInfo.usedGpiopins &= ~gpioFreeMask;

    rx1GpioSelect = TAL_EXTSLICER_RX1_GPIO_DISABLE;

    /* write gain configuration register */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_SLICER_GPIO_CONFIG, rx1GpioSelect);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* read the Rx2 gpio config */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_RX2_SLICER_GPIO_CONFIG, &rx2SendGpio);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);
    rx2GpioConfig = (taliseRx2ExtSlicerGpioSelect_t)rx2SendGpio;

    /* deassign any rx1 gpios already in use */
    if (rx2GpioConfig == TAL_EXTSLICER_RX2_GPIO5_6_7)
    {
         gpioFreeMask = GPIO5_6_7_BITM;
    }
    else if (rx2GpioConfig == TAL_EXTSLICER_RX2_GPIO11_12_13)
    {
        gpioFreeMask |= GPIO11_12_13_BITM;
    }
    else
    {
        gpioFreeMask = 0;
    }

    /* free the unused GPIOs */
    retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, (~gpioFreeMask & GPIO_OE_BITM),  gpioFreeMask);
    IF_ERR_RETURN_U32(retVal);
    device->devStateInfo.usedGpiopins &= ~gpioFreeMask;

    rx2GpioSelect = TAL_EXTSLICER_RX2_GPIO_DISABLE;

    /* write gain configuration register */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_SLICER_GPIO_CONFIG, rx2GpioSelect);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* read the Gpio External Pin Configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, &slicerConfig);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* if pin control is internal then check nibble source to see if gpios are in use */
    /* use case: integer with internal slicer outputting position on Gpios */
    if ((slicerConfig & PIN_CONTROL_BITM) == 0)
    {
        /* read nibble source */
        retVal = (talRecoveryActions_t)TALISE_getGpioSourceCtrl(device, &srcCntrl);
        IF_ERR_RETURN_U32(retVal);

        /* modify the nibble source control if gpios in use*/
        if ((srcCntrl & INTSLICER_NIBBLE_SOURCE) == INTSLICER_NIBBLE_SOURCE)
        {
            srcCntrl &= ~(INTSLICER_NIBBLE_SOURCE);

            /* write nibble source to clear nibbles */
            retVal = (talRecoveryActions_t)TALISE_setGpioSourceCtrl(device, srcCntrl);
            IF_ERR_RETURN_U32(retVal);

            /* turn unused pins to input */
            gpioAssignMask = GPIO8_9_10_BITM | GPIO12_13_14_BITM;
            retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, 0x00, gpioAssignMask);
            IF_ERR_RETURN_U32(retVal);

            /* free the gpios */
            device->devStateInfo.usedGpiopins &= ~gpioAssignMask;
        }
    }

    /* set the configurations per selected mode type Floating Point */
    if (rxDataFormat->formatSelect == TAL_GAIN_WITH_FLOATING_POINT)
    {
         if (rxDataFormat->fpRoundMode > TAL_ROUND_FROM_EVEN)
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_ROUNDMODE_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         if (rxDataFormat->fpDataFormat > 1)
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_FPDATAFRMT_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         if (rxDataFormat->fpEncodeNan > 1)
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_FPENCNAN_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         if (rxDataFormat->fpNumExpBits > TAL_5_EXPONENTBITS)
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_FPEXPBITS_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         if (rxDataFormat->fpHideLeadingOne > 1)
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_FPHIDELEADINGONE_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         if ((rxDataFormat->fpRx1Atten != TAL_FPATTEN_MINUS18DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_MINUS12DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_MINUS6DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_0DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_6DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_12DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_18DB) &&
             (rxDataFormat->fpRx1Atten != TAL_FPATTEN_24DB))
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_FPRX1ATTEN_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         if ((rxDataFormat->fpRx2Atten != TAL_FPATTEN_MINUS18DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_MINUS12DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_MINUS6DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_0DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_6DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_12DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_18DB) &&
             (rxDataFormat->fpRx2Atten != TAL_FPATTEN_24DB))
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                     TAL_ERR_SET_RXDATAFRMT_FPRX2ATTEN_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         /* force embedded bits to zeros */
         /* write integer configuration register */
         halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_INTEGER_FORMAT_CONFIG, 0x02);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         /* assemble and write float point config register */
         fpConfig = ((((((uint8_t)rxDataFormat->fpRoundMode << 5) | (rxDataFormat->fpDataFormat << 4)) |
                  (rxDataFormat->fpEncodeNan << 3)) | ((uint8_t)rxDataFormat->fpNumExpBits << 1)) | rxDataFormat->fpHideLeadingOne);

         halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_CONFIG, fpConfig);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         /* assemble and write rx attenuation register */
         fpAtten = (((rxDataFormat->fpRx2Atten & 0x07) << 3) | (rxDataFormat->fpRx1Atten & 0x07));

         halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_CONTROL, fpAtten);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         /* write the floating point enable to FP on */
         halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_ENABLE, 0x03);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         /* read for gain configuration register */
         halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, &gainConfig);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         gainConfig |= GAIN_COMP_EN_BITM;  /* gain compensation on  */
         gainConfig &= ~PIN_CONTROL_BITM; /* pin control internal  */

         /* write gain configuration register */
         halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, gainConfig, 0xE1, 0);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);
    } /* end FP */

    /* Integer Mode or disabled */
    else
    {

         if (rxDataFormat->intEmbeddedBits == TAL_NO_EMBEDDED_SLICER_BITS)
         {
              intConfig &= ~SLICER_NUMBERBITS_BITM;   /* Set to default */
              intConfig &= ~SLICER_BIT_POSITION_BITM; /* Set to default */
              intConfig &= ~SLICER_EMBED_EN_BITM;     /* Disable embedding slicer in data sample */
         }
         else if (rxDataFormat->intEmbeddedBits == TAL_EMBED_1_SLICERBIT_AT_MSB)
         {
              intConfig |= SLICER_NUMBERBITS_BITM;    /* 1 bit on I, 1 bit on Q */
              intConfig &= ~SLICER_BIT_POSITION_BITM; /* bits after sign at MSB */
              intConfig |= SLICER_EMBED_EN_BITM;      /* slicer embed enabled   */
         }
         else if (rxDataFormat->intEmbeddedBits == TAL_EMBED_1_SLICERBIT_AT_LSB)
         {
              intConfig |= SLICER_NUMBERBITS_BITM;    /* 1 bit on I, 1 bit on Q */
              intConfig |= SLICER_BIT_POSITION_BITM;  /* bits at LSB */
              intConfig |= SLICER_EMBED_EN_BITM;      /* slicer embed enabled   */
         }
         else if (rxDataFormat->intEmbeddedBits == TAL_EMBED_2_SLICERBITS_AT_MSB)
         {
              intConfig &= ~SLICER_NUMBERBITS_BITM;   /* 2 bit on I, 2 bit on Q */
              intConfig &= ~SLICER_BIT_POSITION_BITM; /* bits after sign at MSB */
              intConfig |= SLICER_EMBED_EN_BITM;      /* slicer embed enabled   */
         }
         else if (rxDataFormat->intEmbeddedBits == TAL_EMBED_2_SLICERBITS_AT_LSB)
         {
              intConfig &= ~SLICER_NUMBERBITS_BITM;   /* 2 bit on I, 2 bit on Q */
              intConfig |= SLICER_BIT_POSITION_BITM;  /* bits at LSB */
              intConfig |= SLICER_EMBED_EN_BITM;      /* slicer embed enabled   */
         }

         if (rxDataFormat->intSampleResolution == TAL_INTEGER_12BIT_2SCOMP)
         {
              intConfig &= ~DATA_RESOLUTION_BITM;  /* 12 bit  */
              intConfig &= ~SIGNED_MAGNITUDE_BITM; /* 2s comp */
              npCheck = 12;
         }
         else if (rxDataFormat->intSampleResolution == TAL_INTEGER_12BIT_SIGNED)
         {
              intConfig &= ~DATA_RESOLUTION_BITM;  /* 12 bit */
              intConfig |= SIGNED_MAGNITUDE_BITM;  /* signed */
              npCheck = 12;
         }
         else if (rxDataFormat->intSampleResolution == TAL_INTEGER_16BIT_2SCOMP)
         {
              intConfig |= DATA_RESOLUTION_16BIT;   /* 16 bit  */
              intConfig &= ~SIGNED_MAGNITUDE_BITM;  /* 2s comp */
              npCheck = 16;
         }
         else if (rxDataFormat->intSampleResolution == TAL_INTEGER_16BIT_SIGNED)
         {
              intConfig |= DATA_RESOLUTION_16BIT;   /* 16 bit */
              intConfig |= SIGNED_MAGNITUDE_BITM;   /* signed */
              npCheck = 16;
         }
         else if (rxDataFormat->intSampleResolution == TAL_INTEGER_24BIT_2SCOMP)
         {
              intConfig |= DATA_RESOLUTION_24BIT;   /* 16 bit  */
              intConfig &= ~SIGNED_MAGNITUDE_BITM;  /* 2s comp */
              npCheck = 24;
         }
         else
         {
              intConfig |= DATA_RESOLUTION_24BIT;   /* 16 bit */
              intConfig |= SIGNED_MAGNITUDE_BITM;   /* signed */
              npCheck = 24;
         }
        
        if (rxDataFormat->formatSelect == TAL_GAIN_COMPENSATION_DISABLED)
        {
            intConfig &= ~SLICER_NUMBERBITS_BITM;   /* 2 bit on I, 2 bit on Q */
            intConfig &= ~SLICER_BIT_POSITION_BITM; /* bits after sign at MSB */
            intConfig &= ~SLICER_EMBED_EN_BITM;     /* slicer embed disable */
        }

         /* JESD204 Framer Nprime must be greater than or equal to the intSampleResolution */
         if (((device->devStateInfo.profilesValid & RX_PROFILE_VALID) > 0) &&
              (device->devStateInfo.rxFramerNp < npCheck))
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                 TAL_ERR_SET_RXDATAFRMT_DATARES_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         /* JESD204 Framer Nprime must be greater than or equal to the intSampleResolution */
         if (((device->devStateInfo.profilesValid & ORX_PROFILE_VALID) > 0) &&
              (device->devStateInfo.orxFramerNp < npCheck))
         {
             return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                 TAL_ERR_SET_RXDATAFRMT_DATARES_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
         }

         /* write the floating point enable to FP off */
         halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_ENABLE, 0x00);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         /* write integer configuration register */
         halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_INTEGER_FORMAT_CONFIG, intConfig);
         retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
         IF_ERR_RETURN_U32(retVal);

         if (rxDataFormat->formatSelect == TAL_GAIN_WITH_INTSLICER)
         {
              /* verify needed GPIOs are unused */
              gpioAssignMask = GPIO8_9_10_BITM | GPIO12_13_14_BITM;
              if ((device->devStateInfo.usedGpiopins & gpioAssignMask) > 0)
              {
                  return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                         TAL_ERR_SET_RXDATAFRMT_RX1GPIO_INUSE, retVal, TALACT_ERR_CHECK_PARAM);
              }

              slicerConfig = 0;
              slicerConfig |= GAIN_COMP_EN_BITM;                     /* gain compensation on  */
              slicerConfig &= ~PIN_CONTROL_BITM;                     /* pin control internal  */
              slicerConfig |= ((uint8_t)rxDataFormat->extPinStepSize << 6);   /* set gain step size    */

              /* write gain configuration register */
              halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, slicerConfig, 0xE1, 0);
              retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
              IF_ERR_RETURN_U32(retVal);

              /* read nibble source */
              retVal = (talRecoveryActions_t)TALISE_getGpioSourceCtrl(device, &srcCntrl);
              IF_ERR_RETURN_U32(retVal);

              /* modify the nibble source control to allow outputs on GPIO 8,9,10, 12,13,14 */
              srcCntrl &= INTSLICER_NIBBLE_CLEAR_BITM;  /* clear bits [15:8] */
              srcCntrl |= INTSLICER_NIBBLE_SOURCE;

              /* write nibble source */
              retVal = (talRecoveryActions_t)TALISE_setGpioSourceCtrl(device, srcCntrl);
              IF_ERR_RETURN_U32(retVal);

              /* set used Gpios to output */
              retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, gpioAssignMask, gpioAssignMask);
              IF_ERR_RETURN_U32(retVal);

              /* success so assign the gpios */
              device->devStateInfo.usedGpiopins |= gpioAssignMask;
         } /* end intslicer */
         else if (rxDataFormat->formatSelect == TAL_GAIN_WITH_INTSLICER_NOGPIO)
         {
              slicerConfig = 0;
              slicerConfig |= GAIN_COMP_EN_BITM;                    /* gain compensation on  */
              slicerConfig &= ~PIN_CONTROL_BITM;                    /* pin control internal  */
              slicerConfig |= ((uint8_t)rxDataFormat->extPinStepSize << 6);   /* set gain step size    */

              /* write gain configuration register */
              halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, slicerConfig, 0xE1, 0);
              retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
              IF_ERR_RETURN_U32(retVal);
         } /* end nogpio */
         else if (rxDataFormat->formatSelect == TAL_GAIN_WITH_EXTERNAL_SLICER)
         {
              /* verify that rx1 GPIOs are not disabled */
              if (rxDataFormat->rx1GpioSelect == TAL_EXTSLICER_RX1_GPIO_DISABLE)
              {
                  return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                          TAL_ERR_SET_RXDATAFRMT_EXTSLICER_RX1GPIO_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
              }

              /* verify that rx2 GPIOs are not disabled */
              if (rxDataFormat->rx2GpioSelect == TAL_EXTSLICER_RX2_GPIO_DISABLE)
              {
                  return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                          TAL_ERR_SET_RXDATAFRMT_EXTSLICER_RX2GPIO_INVPARAM, retVal, TALACT_ERR_CHECK_PARAM);
              }

              slicerConfig = 0;
              slicerConfig |= GAIN_COMP_EN_BITM;                     /* gain compensation on  */
              slicerConfig |= PIN_CONTROL_BITM;                     /* pin control external  */
              slicerConfig |= ((uint8_t)rxDataFormat->extPinStepSize << 6);   /* set gain step size    */

              /* write gain configuration register */
              halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, slicerConfig, 0xE1, 0);
              retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
              IF_ERR_RETURN_U32(retVal);

              if (rxDataFormat->rx1GpioSelect == TAL_EXTSLICER_RX1_GPIO0_1_2)
              {
                   gpioAssignMask = GPIO0_1_2_BITM;
                   rx1Gpio = TAL_EXTSLICER_RX1_GPIO0_1_2;
              }
              else if (rxDataFormat->rx1GpioSelect == TAL_EXTSLICER_RX1_GPIO5_6_7)
              {
                   gpioAssignMask = GPIO5_6_7_BITM;
                   rx1Gpio = TAL_EXTSLICER_RX1_GPIO5_6_7;
              }
              else if (rxDataFormat->rx1GpioSelect == TAL_EXTSLICER_RX1_GPIO8_9_10)
              {
                   gpioAssignMask = GPIO8_9_10_BITM;
                   rx1Gpio = TAL_EXTSLICER_RX1_GPIO8_9_10;
              }

              if ((device->devStateInfo.usedGpiopins & gpioAssignMask) > 0)
              {
                   return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                          TAL_ERR_SET_RXDATAFRMT_RX1GPIO_INUSE, retVal, TALACT_ERR_CHECK_PARAM);
              }

              /* success so assign the gpios */
              device->devStateInfo.usedGpiopins |= gpioAssignMask;

              /* write the slicer register contents */
              halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_SLICER_GPIO_CONFIG, rx1Gpio);
              retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
              IF_ERR_RETURN_U32(retVal);
              rx1GpioConfig = (taliseRx1ExtSlicerGpioSelect_t) rx1Gpio;

              if (rxDataFormat->rx2GpioSelect == TAL_EXTSLICER_RX2_GPIO11_12_13)
              {
                   gpioAssignMask = GPIO11_12_13_BITM;
                   rx2Gpio = TAL_EXTSLICER_RX2_GPIO11_12_13;
              }
              else if (rxDataFormat->rx2GpioSelect == TAL_EXTSLICER_RX2_GPIO5_6_7)
              {
                   gpioAssignMask = GPIO5_6_7_BITM;
                   rx2Gpio = TAL_EXTSLICER_RX2_GPIO5_6_7;
              }

              /* check for special case of Rx1 and Rx2 slicer output on same GPIOs */
              if (((device->devStateInfo.usedGpiopins & gpioAssignMask) > 0) &&
                      (rx1GpioConfig != ((int32_t) TAL_EXTSLICER_RX1_GPIO5_6_7)) &&
                      (rxDataFormat->rx2GpioSelect == TAL_EXTSLICER_RX2_GPIO5_6_7))
              {
                  return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                          TAL_ERR_SET_RXDATAFRMT_RX2GPIO_INUSE, retVal, TALACT_ERR_CHECK_PARAM);
              }
              else if (((device->devStateInfo.usedGpiopins & gpioAssignMask) > 0) &&
                      (rxDataFormat->rx2GpioSelect == TAL_EXTSLICER_RX2_GPIO11_12_13))
              {
                  return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                            TAL_ERR_SET_RXDATAFRMT_RX2GPIO_INUSE, retVal, TALACT_ERR_CHECK_PARAM);
              }

              /* Insure Gpios to input */
              retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, (~gpioAssignMask & GPIO_OE_BITM),  gpioAssignMask);
              IF_ERR_RETURN_U32(retVal);

              /* success so assign the gpios */
              device->devStateInfo.usedGpiopins |= gpioAssignMask;

              /* write the slicer register contents */
              halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_SLICER_GPIO_CONFIG, rx2Gpio);
              retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
              IF_ERR_RETURN_U32(retVal);
         } /* end external */
         /* disable gain compensation */
         else if (rxDataFormat->formatSelect == TAL_GAIN_COMPENSATION_DISABLED)
         {
             /* read for gain configuration register */
             halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, &gainConfig);
             retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
             IF_ERR_RETURN_U32(retVal);

             gainConfig &= ~GAIN_COMP_EN_BITM;         /* gain compensation off */
             gainConfig &= ~PIN_CONTROL_BITM;         /* pin control internal  */

             /* write gain configuration register */
             halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, gainConfig, 0xE1, 0);
             retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
             IF_ERR_RETURN_U32(retVal);
         }
    } /* end integer mode */

    return (uint32_t)retVal;
} /* end TALISE_setRxDataFormat */

uint32_t TALISE_getRxDataFormat(taliseDevice_t *device, taliseRxDataFormat_t *rxDataFormat)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

    uint8_t config = 0;
    uint8_t fpEnable = 0;
    uint8_t intConfig = 0;
    uint8_t intResolution = 0;
    uint8_t gainEn = 0;
    uint32_t srcCntrl = 0;

    static const uint8_t GAIN_COMP_EN_BITM = 0x01;
    static const uint8_t PIN_CONTROL_BITM = 0x20;
    static const uint8_t EXT_LNA_COMP_BITM = 0x02;
    static const uint8_t TEMP_GAIN_BITM = 0x01;
    static const uint8_t ROUND_MODE_BITM = 0xE0;
    static const uint8_t MSBLSB_FORMAT_BITM = 0x10;
    static const uint8_t NUM_EXPBITS_BITM = 0x06;
    static const uint8_t FP_ENCNAN_BITM = 0x08;
    static const uint8_t FP_ENABLE_BITM = 0x03;
    static const uint8_t HIDE_LEADING_ONES_BITM = 0x01;
    static const uint8_t RX2_ATTEN_BITM = 0x38;
    static const uint8_t RX1_ATTEN_BITM = 0x07;
    static const uint8_t SLICER_NUMBER_BITM = 0x20;
    static const uint8_t SLICER_POSITION_BITM = 0x10;
    static const uint8_t EMBED_SLICER_BITM = 0x08;
    static const uint8_t SLICER_STEPSIZE_BITM = 0xC0;
    static const uint8_t DATA_RESOLUTION_BITM = 0x06;
    static const uint8_t DATA_RESOLUTION_16BIT = 0x02;
    static const uint8_t DATA_RESOLUTION_24BIT = 0x04;
    static const uint8_t SIGNED_MAGNITUDE_BITM = 0x01;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getRxDataFormat()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (rxDataFormat == NULL)
    {
         return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                 TAL_ERR_GET_DATAFORMAT_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* fetch the floating point configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_CONFIG, &config);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    rxDataFormat->fpRoundMode = (taliseFpRoundModes_t) ((config & ROUND_MODE_BITM) >> 5);
    rxDataFormat->fpDataFormat = ((config & MSBLSB_FORMAT_BITM) >> 4);
    rxDataFormat->fpEncodeNan = ((config & FP_ENCNAN_BITM) >> 3);
    rxDataFormat->fpNumExpBits = (taliseFpExponentModes_t) ((config & NUM_EXPBITS_BITM) >> 1);
    rxDataFormat->fpHideLeadingOne = (config & HIDE_LEADING_ONES_BITM);

    /* fetch the Rx Attenuation */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_CONTROL, &config);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    rxDataFormat->fpRx2Atten = (taliseFpAttenSteps_t) ((config & RX2_ATTEN_BITM) >> 3);
    rxDataFormat->fpRx1Atten = (taliseFpAttenSteps_t) (config & RX1_ATTEN_BITM);

    /* fetch the Integer configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_INTEGER_FORMAT_CONFIG, &intConfig);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    if ((intConfig & EMBED_SLICER_BITM) > 0)
    {
        if (((intConfig & SLICER_NUMBER_BITM) > 0) &&
            ((intConfig & SLICER_POSITION_BITM) > 0))
        {
            rxDataFormat->intEmbeddedBits = TAL_EMBED_1_SLICERBIT_AT_LSB;
        }
        else if (((intConfig & SLICER_NUMBER_BITM) == 0) &&
                 ((intConfig & SLICER_POSITION_BITM) > 0))
        {
            rxDataFormat->intEmbeddedBits = TAL_EMBED_2_SLICERBITS_AT_LSB;
        }
        else if (((intConfig & SLICER_NUMBER_BITM) > 0) &&
                 ((intConfig & SLICER_POSITION_BITM) == 0))
        {
            rxDataFormat->intEmbeddedBits = TAL_EMBED_1_SLICERBIT_AT_MSB;
        }
        else
        {
            rxDataFormat->intEmbeddedBits = TAL_EMBED_2_SLICERBITS_AT_MSB;
        }
    }
    else
    {
        rxDataFormat->intEmbeddedBits = TAL_NO_EMBEDDED_SLICER_BITS;
    }

    /* fetch the Integer data resolution */
    intResolution = intConfig;

    if (((intResolution & DATA_RESOLUTION_BITM) == 0) &&
        ((intResolution & SIGNED_MAGNITUDE_BITM) > 0))
    {
         rxDataFormat->intSampleResolution = TAL_INTEGER_12BIT_SIGNED;
    }
    else if (((intResolution & DATA_RESOLUTION_BITM) == 0) &&
             ((intResolution & SIGNED_MAGNITUDE_BITM) == 0))
    {
         rxDataFormat->intSampleResolution = TAL_INTEGER_12BIT_2SCOMP;
    }
    else if (((intResolution & DATA_RESOLUTION_BITM) == DATA_RESOLUTION_16BIT) &&
             ((intResolution & SIGNED_MAGNITUDE_BITM) > 0))
    {
         rxDataFormat->intSampleResolution = TAL_INTEGER_16BIT_SIGNED;
    }
    else if (((intResolution & DATA_RESOLUTION_BITM) == DATA_RESOLUTION_16BIT) &&
             ((intResolution & SIGNED_MAGNITUDE_BITM) == 0))
    {
         rxDataFormat->intSampleResolution = TAL_INTEGER_16BIT_2SCOMP;
    }
    else if (((intResolution & DATA_RESOLUTION_BITM) == DATA_RESOLUTION_24BIT) &&
             ((intResolution & SIGNED_MAGNITUDE_BITM) > 0))
    {
         rxDataFormat->intSampleResolution = TAL_INTEGER_24BIT_SIGNED;
    }
    else
    {
        rxDataFormat->intSampleResolution = TAL_INTEGER_24BIT_2SCOMP;
    }

    /* fetch the Floating Point enable */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_FLOATING_POINT_ENABLE, &fpEnable);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* fetch the gain control configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_GAIN_COMPENATION_AND_SLICER_CONFIG, &gainEn);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    rxDataFormat->extPinStepSize = (taliseGainStepSize_t) ((gainEn & SLICER_STEPSIZE_BITM) >> 6);

    /* fetch the rx1 gpio configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_RX1_SLICER_GPIO_CONFIG, &config);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    rxDataFormat->rx1GpioSelect = (taliseRx1ExtSlicerGpioSelect_t) config;

    /* fetch the rx2 gpio configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_RX2_SLICER_GPIO_CONFIG, &config);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    rxDataFormat->rx2GpioSelect = (taliseRx2ExtSlicerGpioSelect_t) config;

    if ((gainEn & GAIN_COMP_EN_BITM) > 0)
    {
        if ((fpEnable & FP_ENABLE_BITM) > 0)
        {
            rxDataFormat->formatSelect = TAL_GAIN_WITH_FLOATING_POINT;
        }
        else if ((gainEn & PIN_CONTROL_BITM) > 0)
        {
            rxDataFormat->formatSelect = TAL_GAIN_WITH_EXTERNAL_SLICER;
        }
        else
        {
            /* read nibble source */
            retVal = (talRecoveryActions_t)TALISE_getGpioSourceCtrl(device, &srcCntrl);
            IF_ERR_RETURN_U32(retVal);

            /* modify the nibble source control */
            if ((srcCntrl & 0xFF00) == ((TAL_GPIO_SLICER_OUT_MODE << 12) | (TAL_GPIO_SLICER_OUT_MODE << 8)))
            {
                rxDataFormat->formatSelect = TAL_GAIN_WITH_INTSLICER;
            }
            else
            {
                rxDataFormat->formatSelect = TAL_GAIN_WITH_INTSLICER_NOGPIO;
            }
        }
    }
    else
    {
        rxDataFormat->formatSelect = TAL_GAIN_COMPENSATION_DISABLED;
    }

    /* fetch the misc gain configuration */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_GAIN_COMPENSATION_AND_SLICER_CONFIG2, &config);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    rxDataFormat->externalLnaGain = ((config & EXT_LNA_COMP_BITM) >> 1);
    rxDataFormat->tempCompensationEnable = (config & TEMP_GAIN_BITM);

    return (uint32_t)retVal;
}

uint32_t TALISE_getSlicerPosition(taliseDevice_t *device, uint8_t *rx1SlicerPosition, uint8_t *rx2SlicerPosition)
{

    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t slicerPosition = 0;
    static const uint8_t POSITION_MASK = 0x07;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getSlicerPosition()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if ((rx1SlicerPosition == NULL) ||
        (rx2SlicerPosition == NULL))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_GET_SLICERPOS_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* read the slicer positions */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_RXDP_SLICER_READBACK, &slicerPosition);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    *rx1SlicerPosition = slicerPosition & POSITION_MASK;
    *rx2SlicerPosition = (slicerPosition >> 3) & POSITION_MASK;

    return (uint32_t)retVal;
}

static talRecoveryActions_t talSetRx1GainCtrlPin (taliseDevice_t *device, uint8_t enable, taliseGpioPinSel_t rxGainIncPin, taliseGpioPinSel_t rxGainDecPin)
{
    uint8_t registerValue = 0;
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint32_t usedGpiopins = 0;
    uint32_t gpioFreeMask = 0;
    uint32_t gpioUsedMask = 0;

    static const uint16_t TAL_RX1_INC_GAIN_GPIO0   = 0x00;
    static const uint16_t TAL_RX1_INC_GAIN_GPIO10  = 0x01;
    static const uint16_t TAL_RX1_INC_GAIN_DISABLE = 0x03;
    static const uint16_t TAL_RX1_DEC_GAIN_GPIO1   = 0x00;
    static const uint16_t TAL_RX1_DEC_GAIN_GPIO11  = 0x01;
    static const uint16_t TAL_RX1_DEC_GAIN_DISABLE = 0x03;


    uint16_t rx1GainIncPinSel = TAL_RX1_INC_GAIN_DISABLE;
    uint16_t rx1GainDecPinSel = TAL_RX1_DEC_GAIN_DISABLE;

    /* Free all used GPIO's based on current configuration*/
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX1, &registerValue);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);
    rx1GainIncPinSel = (uint16_t)((registerValue >> 4) & 0x03);
    rx1GainDecPinSel = (uint16_t)((registerValue >> 2) & 0x03);

    if (rx1GainIncPinSel == TAL_RX1_INC_GAIN_GPIO0)
    {
        gpioFreeMask |= (1 << TAL_GPIO_00);
    }

    else if (rx1GainIncPinSel == TAL_RX1_INC_GAIN_GPIO10)
    {
        gpioFreeMask |= (1 << TAL_GPIO_10);
    }

    if (rx1GainDecPinSel == TAL_RX1_DEC_GAIN_GPIO1)
    {
        gpioFreeMask |= (1 << TAL_GPIO_01);
    }

    else if (rx1GainDecPinSel == TAL_RX1_DEC_GAIN_GPIO11)
    {
        gpioFreeMask |= (1 << TAL_GPIO_11);
    }

    usedGpiopins = device->devStateInfo.usedGpiopins & ~gpioFreeMask;

    /* check if GPIO's are available for the new configuration*/
    if (enable > 0)
    {
        gpioUsedMask |= (1 << rxGainIncPin);
        gpioUsedMask |= (1 << rxGainDecPin);

        if ((usedGpiopins & gpioUsedMask) != 0)
        {
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_RX1_GPIO_IN_USE, retVal, TALACT_ERR_CHECK_PARAM);
        }

        usedGpiopins |= gpioUsedMask;
        rx1GainIncPinSel = (rxGainIncPin == TAL_GPIO_00) ? TAL_RX1_INC_GAIN_GPIO0 : TAL_RX1_INC_GAIN_GPIO10;
        rx1GainDecPinSel = (rxGainDecPin == TAL_GPIO_01) ? TAL_RX1_DEC_GAIN_GPIO1 : TAL_RX1_DEC_GAIN_GPIO11;
    }
    else
    {
        rx1GainIncPinSel = TAL_RX1_INC_GAIN_DISABLE;
        rx1GainDecPinSel = TAL_RX1_DEC_GAIN_DISABLE;
    }

    /* Program Pin mode configuration */
    registerValue = (((uint8_t)rx1GainIncPinSel) << 4) | (((uint8_t)rx1GainDecPinSel) << 2) | ((enable > 0) ? 0x01 : 0x00);
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX1, registerValue, 0x3D, 0);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Set GPIO input enables */
    /* - Set OE for all freed GPIO's to 0 (input) */
    /* - Set OE for all used GPIO's to 0 (input) */
    retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, 0, (gpioUsedMask | gpioFreeMask));
    IF_ERR_RETURN(retVal);

    /* Update used and freed GPIO's */
    device->devStateInfo.usedGpiopins = usedGpiopins;

    return retVal;
}

static talRecoveryActions_t talSetRx2GainCtrlPin (taliseDevice_t *device, uint8_t enable, taliseGpioPinSel_t rxGainIncPin, taliseGpioPinSel_t rxGainDecPin)
{
    uint8_t registerValue = 0;
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint32_t usedGpiopins = 0;
    uint32_t gpioFreeMask = 0;
    uint32_t gpioUsedMask = 0;

    static const uint16_t TAL_RX2_INC_GAIN_GPIO3   = 0x00;
    static const uint16_t TAL_RX2_INC_GAIN_GPIO13  = 0x01;
    static const uint16_t TAL_RX2_INC_GAIN_DISABLE = 0x03;
    static const uint16_t TAL_RX2_DEC_GAIN_GPIO4   = 0x00;
    static const uint16_t TAL_RX2_DEC_GAIN_GPIO14  = 0x01;
    static const uint16_t TAL_RX2_DEC_GAIN_DISABLE = 0x03;

    uint16_t rx2GainIncPinSel = TAL_RX2_INC_GAIN_DISABLE;
    uint16_t rx2GainDecPinSel = TAL_RX2_DEC_GAIN_DISABLE;

    /* Free all used GPIO's based on current configuration*/
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX2, &registerValue);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);
    rx2GainIncPinSel = (uint16_t)((registerValue >> 4) & 0x03);
    rx2GainDecPinSel = (uint16_t)((registerValue >> 2) & 0x03);

    if (rx2GainIncPinSel == TAL_RX2_INC_GAIN_GPIO3)
    {
        gpioFreeMask |= (1 << TAL_GPIO_03);
    }

    else if (rx2GainIncPinSel == TAL_RX2_INC_GAIN_GPIO13)
    {
        gpioFreeMask |= (1 << TAL_GPIO_13);
    }

    if (rx2GainDecPinSel == TAL_RX2_DEC_GAIN_GPIO4)
    {
        gpioFreeMask |= (1 << TAL_GPIO_04);
    }

    else if (rx2GainDecPinSel == TAL_RX2_DEC_GAIN_GPIO14)
    {
        gpioFreeMask |= (1 << TAL_GPIO_14);
    }

    usedGpiopins = device->devStateInfo.usedGpiopins & ~gpioFreeMask;

    /* check if GPIO's are available for the new configuration*/
    if (enable > 0)
    {
        gpioUsedMask |= (1 << rxGainIncPin);
        gpioUsedMask |= (1 << rxGainDecPin);

        if ((usedGpiopins & gpioUsedMask) != 0)
        {
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_RX2_GPIO_IN_USE, retVal, TALACT_ERR_CHECK_PARAM);
        }

        usedGpiopins |= gpioUsedMask;
        rx2GainIncPinSel = (rxGainIncPin == TAL_GPIO_03) ? TAL_RX2_INC_GAIN_GPIO3 : TAL_RX2_INC_GAIN_GPIO13;
        rx2GainDecPinSel = (rxGainDecPin == TAL_GPIO_04) ? TAL_RX2_DEC_GAIN_GPIO4 : TAL_RX2_DEC_GAIN_GPIO14;
    }
    else
    {
        rx2GainIncPinSel = TAL_RX2_INC_GAIN_DISABLE;
        rx2GainDecPinSel = TAL_RX2_DEC_GAIN_DISABLE;
    }

    /* Program Pin mode configuration */
    registerValue = (((uint8_t)rx2GainIncPinSel) << 4) | (((uint8_t)rx2GainDecPinSel) << 2) | ((enable > 0) ? 0x01 : 0x00);
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX2, registerValue, 0x3D, 0);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Set GPIO input enables */
    /* - Set OE for all freed GPIO's to 0 (input) */
    /* - Set OE for all used GPIO's to 0 (input) */
    retVal = (talRecoveryActions_t)TALISE_setGpioOe(device, 0, (gpioUsedMask | gpioFreeMask));
    IF_ERR_RETURN(retVal);

    /* Update used and freed GPIO's */
    device->devStateInfo.usedGpiopins = usedGpiopins;

    return retVal;
}

uint32_t TALISE_setRxGainCtrlPin(taliseDevice_t *device, taliseRxChannels_t rxChannel, taliseRxGainCtrlPin_t *rxGainCtrlPin)
{
    uint8_t regVal = 0;
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    static const uint8_t MAX_STEP = 0x07;

#if TALISE_VERBOSE
    halError =talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setRxGainCtrlPin()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    switch (rxChannel)
    {
        case TAL_RX1:
            if ( rxGainCtrlPin->enable > 0 )
            {
                if ((rxGainCtrlPin->rxGainIncPin != TAL_GPIO_00) && (rxGainCtrlPin->rxGainIncPin != TAL_GPIO_10))
                {
                    return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_RX1_INC_PIN, retVal, TALACT_ERR_CHECK_PARAM);
                }

                if ((rxGainCtrlPin->rxGainDecPin != TAL_GPIO_01) && (rxGainCtrlPin->rxGainDecPin != TAL_GPIO_11))
                {
                    return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_RX1_DEC_PIN, retVal, TALACT_ERR_CHECK_PARAM);
                }
            }
            retVal = talSetRx1GainCtrlPin(device, rxGainCtrlPin->enable, rxGainCtrlPin->rxGainIncPin, rxGainCtrlPin->rxGainDecPin);
            IF_ERR_RETURN_U32(retVal);
            break;

        case TAL_RX2:
            if (rxGainCtrlPin->enable > 0)
            {
                if ((rxGainCtrlPin->rxGainIncPin != TAL_GPIO_03) && (rxGainCtrlPin->rxGainIncPin != TAL_GPIO_13))
                {
                    return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_RX2_INC_PIN, retVal, TALACT_ERR_CHECK_PARAM);
                }

                if ((rxGainCtrlPin->rxGainDecPin != TAL_GPIO_04) && (rxGainCtrlPin->rxGainDecPin != TAL_GPIO_14))
                {
                    return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_RX2_DEC_PIN, retVal, TALACT_ERR_CHECK_PARAM);
                }
            }
            retVal = talSetRx2GainCtrlPin(device, rxGainCtrlPin->enable, rxGainCtrlPin->rxGainIncPin, rxGainCtrlPin->rxGainDecPin);
            IF_ERR_RETURN_U32(retVal);
            break;

        default:
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
            }
    }

    /* Error checking for gain steps. */
    if (rxGainCtrlPin->incStep > MAX_STEP)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_INC_STEP, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (rxGainCtrlPin->decStep > MAX_STEP)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETRXMGCPINCTRL_INV_DEC_STEP, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Write Gain step */
   regVal = (rxGainCtrlPin->incStep << 3) | rxGainCtrlPin->decStep;
   halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MANUAL_GAIN_CONFIG, regVal);
   retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
   IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_getRxGainCtrlPin(taliseDevice_t *device, taliseRxChannels_t rxChannel, taliseRxGainCtrlPin_t *rxGainCtrlPin)
{
    uint8_t regVal = 0;
    uint8_t pinSel = 0;
    uint16_t mgcConfigAddr = 0;
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

#if TALISE_VERBOSE
    halError =talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getRxGainCtrlPin()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* Read current value of Gain inc/dec and enable */
    switch (rxChannel)
    {
        case TAL_RX1:
            mgcConfigAddr = TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX1;
            break;

        case TAL_RX2:
            mgcConfigAddr = TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX2;
            break;

        default:
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETRXMGCPINCTRL_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
            }
    }

    /*Check passed pointers for NULL */
    if (rxGainCtrlPin == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_GETRXMGCPINCTRL_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Gain Inc, Gain dec, enable  */
    halError = talSpiReadByte(device->devHalInfo, mgcConfigAddr, &regVal);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);
    pinSel = (regVal >> 4) & 0x03;
    rxGainCtrlPin->rxGainIncPin = (rxChannel == TAL_RX1) ? ((pinSel == 0x00) ? TAL_GPIO_00 : (( pinSel == 0x01) ? TAL_GPIO_10 : TAL_GPIO_INVALID))
                                                         : ((pinSel == 0x00) ? TAL_GPIO_03 : (( pinSel == 0x01) ? TAL_GPIO_13 : TAL_GPIO_INVALID));
    pinSel = (regVal >> 2) & 0x03;
    rxGainCtrlPin->rxGainDecPin = (rxChannel == TAL_RX1) ? ((pinSel == 0x00) ? TAL_GPIO_01 : (( pinSel == 0x01) ? TAL_GPIO_11 : TAL_GPIO_INVALID))
                                                         : ((pinSel == 0x00) ? TAL_GPIO_04 : (( pinSel == 0x01) ? TAL_GPIO_14 : TAL_GPIO_INVALID));
    rxGainCtrlPin->enable = regVal & 0x01;

    /* Gain step */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_MANUAL_GAIN_CONFIG, &regVal);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);
    rxGainCtrlPin->incStep = (regVal >> 3) & 0x7;
    rxGainCtrlPin->decStep = regVal & 0x7;

    return (uint32_t)retVal;
}

talRecoveryActions_t talSetDualBandSettings(taliseDevice_t *device, taliseInit_t *init)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    int32_t pfirFs_kHz = 0;
    int32_t pfirFsDiv2_kHz = 0;
    int32_t outFs_kHz = 0;
    int32_t outFsDiv2_kHz = 0;
    int32_t upperBandBandwidthDiv2_kHz = 0;
    int32_t lowerBandBandwidthDiv2_kHz = 0;
    int32_t bandSeparation_kHz = 0;
    int32_t maxLowerBandShiftCenterFreq_kHz = 0;
    int32_t minLowerBandShiftCenterFreq_kHz = 0;
    int32_t lowerBandShiftCenterFreq_kHz = 0;
    int32_t lowerBandNco1Freq_kHz = 0;
    int32_t maxUpperBandShiftCenterFreq_kHz = 0;
    int32_t minUpperBandShiftCenterFreq_kHz = 0;
    int32_t upperBandShiftCenterFreq_kHz = 0;
    int32_t upperBandNco1Freq_kHz = 0;
    int32_t lowerBandNco2Freq_kHz = 0;
    int32_t upperBandNco2Freq_kHz = 0;
    uint32_t lowerBandNco1FreqUnsigned_kHz = 0;
    uint32_t upperBandNco1FreqUnsigned_kHz = 0;
    uint32_t lowerBandNco2FreqUnsigned_kHz = 0;
    uint32_t upperBandNco2FreqUnsigned_kHz = 0;
    uint64_t lowerBandNco1Ftw = 0;
    uint64_t upperBandNco1Ftw = 0;
    uint64_t lowerBandNco2Ftw = 0;
    uint64_t upperBandNco2Ftw = 0;

    int32_t inUpperBandCenterFreq_kHz = 0;
    int32_t inLowerBandCenterFreq_kHz = 0;
    int32_t outUpperBandCenterFreq_kHz = 0;
    int32_t outLowerBandCenterFreq_kHz = 0;

    static const uint64_t POW_2_32 = ((uint64_t)1) << 32;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "talSetDualBandSettings()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    inUpperBandCenterFreq_kHz = init->rx.rxProfile.rxNcoShifterCfg.bandAInputCenterFreq_kHz;
    inLowerBandCenterFreq_kHz = init->rx.rxProfile.rxNcoShifterCfg.bandBInputCenterFreq_kHz;

    outUpperBandCenterFreq_kHz = inUpperBandCenterFreq_kHz + init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz +
                                 init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz;
    outLowerBandCenterFreq_kHz = inLowerBandCenterFreq_kHz + init->rx.rxProfile.rxNcoShifterCfg.bandBNco1Freq_kHz +
                                 init->rx.rxProfile.rxNcoShifterCfg.bandBNco2Freq_kHz;

    /* Fs at output of PFIR : Twice output rate due to decimation in DDC */
    pfirFsDiv2_kHz = device->devStateInfo.rxOutputRate_kHz;
    pfirFs_kHz = pfirFsDiv2_kHz << 1;

    /* Output Fs and Fs/2 */
    outFs_kHz = pfirFsDiv2_kHz;
    outFsDiv2_kHz = outFs_kHz >> 1;

    /* Bandwidth /2 */
    upperBandBandwidthDiv2_kHz = (init->rx.rxProfile.rxNcoShifterCfg.bandAInputBandWidth_kHz >> 1);
    lowerBandBandwidthDiv2_kHz = (init->rx.rxProfile.rxNcoShifterCfg.bandBInputBandWidth_kHz >> 1);

    /* Check : Center frequency of input lower band is less than input upper band */
    if (inLowerBandCenterFreq_kHz > inUpperBandCenterFreq_kHz)
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_INV_CENTER_FREQ, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check : Band should be separated by at least 1 khz */
    if (((inUpperBandCenterFreq_kHz - upperBandBandwidthDiv2_kHz) -
         (inLowerBandCenterFreq_kHz + lowerBandBandwidthDiv2_kHz)) < 0)
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_INV_BAND_SEP, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check : Upper end of upper band input is less than +PfirFs/2 */
    if ((inUpperBandCenterFreq_kHz + upperBandBandwidthDiv2_kHz) > pfirFsDiv2_kHz)
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_INV_IN_UPPER_FREQ, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check : Lower end of lower band input is more than -PfirFs/2 */
    if ((inLowerBandCenterFreq_kHz - lowerBandBandwidthDiv2_kHz) < -pfirFsDiv2_kHz)
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_INV_IN_LOWER_FREQ, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check : upper band output is between -OutFs/2 and  +OutFs/2 */
    if (((outUpperBandCenterFreq_kHz + upperBandBandwidthDiv2_kHz) > outFsDiv2_kHz) ||
        ((outUpperBandCenterFreq_kHz - upperBandBandwidthDiv2_kHz) < -outFsDiv2_kHz))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_INV_OUT_UPPER_FREQ, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check : lower band output is between -OutFs/2 and  +OutFs/2 */
    if (((outLowerBandCenterFreq_kHz + lowerBandBandwidthDiv2_kHz) > outFsDiv2_kHz) ||
        ((outLowerBandCenterFreq_kHz - lowerBandBandwidthDiv2_kHz) < -outFsDiv2_kHz))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_INV_OUT_LOWER_FREQ, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check: Output upper and lower bands dont overlap */
    /* Error if 'lower end of lowerBand' < 'higher end of upperBand' and 'lower end of upperBand' < 'higher end of lowerBand' */
    if (((outLowerBandCenterFreq_kHz - lowerBandBandwidthDiv2_kHz) <
         (outUpperBandCenterFreq_kHz + upperBandBandwidthDiv2_kHz)) &&
        ((outUpperBandCenterFreq_kHz - upperBandBandwidthDiv2_kHz) <
         (outLowerBandCenterFreq_kHz + lowerBandBandwidthDiv2_kHz)))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_OUT_OVERLAP, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Separation between the two bands */
    bandSeparation_kHz = (pfirFs_kHz - lowerBandBandwidthDiv2_kHz - upperBandBandwidthDiv2_kHz -
            (inUpperBandCenterFreq_kHz - inLowerBandCenterFreq_kHz));

    /* Move lower band up to the upper end of DEC2 passband. */
    /* This value assumes that the upper band does not alias back into the lower side of DEC2 passband */
    maxLowerBandShiftCenterFreq_kHz = (outFsDiv2_kHz - lowerBandBandwidthDiv2_kHz);

    /* This value assumes that upper band can alias back into lower side of DEC2 passband. The shift is hence limited by band separation  */
    minLowerBandShiftCenterFreq_kHz = (-outFsDiv2_kHz + bandSeparation_kHz + lowerBandBandwidthDiv2_kHz);

    /* The value that the lower band can be shifted upwards is the minimum of the two values */
    lowerBandShiftCenterFreq_kHz = (maxLowerBandShiftCenterFreq_kHz < minLowerBandShiftCenterFreq_kHz) ? maxLowerBandShiftCenterFreq_kHz : minLowerBandShiftCenterFreq_kHz;

    /* NCO1 Frequency to tune to for lower band: NCO frequency = Fout - Fin , since I and Q are swapped */
    lowerBandNco1Freq_kHz = (lowerBandShiftCenterFreq_kHz - inLowerBandCenterFreq_kHz);

    /* Move upper band down to the lower end of DEC2 passband. */
    /* This value assumes that the lower band does not alias back into the upper side of DEC2 passband */
    maxUpperBandShiftCenterFreq_kHz = (-outFsDiv2_kHz + upperBandBandwidthDiv2_kHz);

    /* This value assumes that lower band can alias back into upper side of DEC2 passband. The shift is hence limited by band separation  */
    minUpperBandShiftCenterFreq_kHz = (outFsDiv2_kHz - bandSeparation_kHz - upperBandBandwidthDiv2_kHz) ;

    /* The value that the Upper band can be shifted downwards is the max of the two values */
    upperBandShiftCenterFreq_kHz = (maxUpperBandShiftCenterFreq_kHz > minUpperBandShiftCenterFreq_kHz) ? maxUpperBandShiftCenterFreq_kHz : minUpperBandShiftCenterFreq_kHz;

    /* NCO1 Frequency to tune to for upper: NCO frequency = Fout - Fin , since I and Q are swapped*/
    upperBandNco1Freq_kHz = (upperBandShiftCenterFreq_kHz - inUpperBandCenterFreq_kHz);

    /* To convert from lowerBandShiftCenterFreq_kHz to outLowerBandCenterFreq_kHz */
    lowerBandNco2Freq_kHz = (outLowerBandCenterFreq_kHz - lowerBandShiftCenterFreq_kHz);

    /* To convert from upperBandShiftCenterFreq_kHz to outUpperBandCenterFreq_kHz */
    upperBandNco2Freq_kHz = (outUpperBandCenterFreq_kHz - upperBandShiftCenterFreq_kHz);

    /* Convert negative to positive frequencies */
    lowerBandNco1FreqUnsigned_kHz = (lowerBandNco1Freq_kHz > 0) ? lowerBandNco1Freq_kHz : (pfirFs_kHz + lowerBandNco1Freq_kHz);
    upperBandNco1FreqUnsigned_kHz = (upperBandNco1Freq_kHz > 0) ? upperBandNco1Freq_kHz : (pfirFs_kHz + upperBandNco1Freq_kHz);
    lowerBandNco2FreqUnsigned_kHz = (lowerBandNco2Freq_kHz > 0) ? lowerBandNco2Freq_kHz : (outFs_kHz + lowerBandNco2Freq_kHz);
    upperBandNco2FreqUnsigned_kHz = (upperBandNco2Freq_kHz > 0) ? upperBandNco2Freq_kHz : (outFs_kHz + upperBandNco2Freq_kHz);

    /* Convert positive frequencies to their FTW equivalents */
    lowerBandNco1Ftw = ((((uint64_t)lowerBandNco1FreqUnsigned_kHz * POW_2_32) << 1) + pfirFs_kHz) / (pfirFs_kHz << 1); /* integer rounding */
    upperBandNco1Ftw = ((((uint64_t)upperBandNco1FreqUnsigned_kHz * POW_2_32) << 1) + pfirFs_kHz) / (pfirFs_kHz << 1); /* integer rounding */
    lowerBandNco2Ftw = ((((uint64_t)lowerBandNco2FreqUnsigned_kHz * POW_2_32) << 1) + outFs_kHz) / (outFs_kHz << 1); /* integer rounding */
    upperBandNco2Ftw = ((((uint64_t)upperBandNco2FreqUnsigned_kHz * POW_2_32) << 1) + outFs_kHz) / (outFs_kHz << 1); /* integer rounding */

    /* Check FTW is not more than 32 bits */
    if ((lowerBandNco1Ftw >= POW_2_32) || (upperBandNco1Ftw >= POW_2_32) ||
        (lowerBandNco2Ftw >= POW_2_32) || (upperBandNco2Ftw >= POW_2_32))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETDUALBANDSETTINGS_FTW_OVRG, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Write to FTW - lower Band NCO 1*/
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH1_FTW_BYTE4, (uint8_t)(lowerBandNco1Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH1_FTW_BYTE3, (uint8_t)(lowerBandNco1Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH1_FTW_BYTE2, (uint8_t)(lowerBandNco1Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH1_FTW_BYTE1, (uint8_t)(lowerBandNco1Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH2_FTW_BYTE4, (uint8_t)(lowerBandNco1Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH2_FTW_BYTE3, (uint8_t)(lowerBandNco1Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH2_FTW_BYTE2, (uint8_t)(lowerBandNco1Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_CH2_FTW_BYTE1, (uint8_t)(lowerBandNco1Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Write to FTW - upper Band NCO 1*/
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO1_FTW_BYTE4, (uint8_t)(upperBandNco1Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO1_FTW_BYTE3, (uint8_t)(upperBandNco1Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO1_FTW_BYTE2, (uint8_t)(upperBandNco1Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO1_FTW_BYTE1, (uint8_t)(upperBandNco1Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO1_FTW_BYTE4, (uint8_t)(upperBandNco1Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO1_FTW_BYTE3, (uint8_t)(upperBandNco1Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO1_FTW_BYTE2, (uint8_t)(upperBandNco1Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO1_FTW_BYTE1, (uint8_t)(upperBandNco1Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Write to FTW - lower Band NCO 2*/
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_A_NCO2_FTW_BYTE4, (uint8_t)(lowerBandNco2Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_A_NCO2_FTW_BYTE3, (uint8_t)(lowerBandNco2Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_A_NCO2_FTW_BYTE2, (uint8_t)(lowerBandNco2Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_A_NCO2_FTW_BYTE1, (uint8_t)(lowerBandNco2Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_A_NCO2_FTW_BYTE4, (uint8_t)(lowerBandNco2Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_A_NCO2_FTW_BYTE3, (uint8_t)(lowerBandNco2Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_A_NCO2_FTW_BYTE2, (uint8_t)(lowerBandNco2Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_A_NCO2_FTW_BYTE1, (uint8_t)(lowerBandNco2Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Write to FTW - upper Band NCO 2*/
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO2_FTW_BYTE4, (uint8_t)(upperBandNco2Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO2_FTW_BYTE3, (uint8_t)(upperBandNco2Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO2_FTW_BYTE2, (uint8_t)(upperBandNco2Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_BAND_B_NCO2_FTW_BYTE1, (uint8_t)(upperBandNco2Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO2_FTW_BYTE4, (uint8_t)(upperBandNco2Ftw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO2_FTW_BYTE3, (uint8_t)(upperBandNco2Ftw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO2_FTW_BYTE2, (uint8_t)(upperBandNco2Ftw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_BAND_B_NCO2_FTW_BYTE1, (uint8_t)(upperBandNco2Ftw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Update FTW words */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_FTW_UPDATE_CONTROL, 0xFF);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    return retVal;
}

static talRecoveryActions_t talSetRxNcoFtw(taliseDevice_t *device, taliseRxNcoChannel_t rxNcoChannel, uint32_t ncoFtw)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t spiAddr = 0;

    switch(rxNcoChannel)
    {
        case TAL_RX1_NCO1A: spiAddr = TALISE_ADDR_RX_NCO_CH1_FTW_BYTE4; break;
        case TAL_RX1_NCO1B: spiAddr = TALISE_ADDR_RX1_BAND_B_NCO1_FTW_BYTE4; break;
        case TAL_RX1_NCO2A: spiAddr = TALISE_ADDR_RX1_BAND_A_NCO2_FTW_BYTE4; break;
        case TAL_RX1_NCO2B: spiAddr = TALISE_ADDR_RX1_BAND_B_NCO2_FTW_BYTE4; break;
        case TAL_RX2_NCO1A: spiAddr = TALISE_ADDR_RX_NCO_CH2_FTW_BYTE4; break;
        case TAL_RX2_NCO1B: spiAddr = TALISE_ADDR_RX2_BAND_B_NCO1_FTW_BYTE4; break;
        case TAL_RX2_NCO2A: spiAddr = TALISE_ADDR_RX2_BAND_A_NCO2_FTW_BYTE4; break;
        case TAL_RX2_NCO2B: spiAddr = TALISE_ADDR_RX2_BAND_B_NCO2_FTW_BYTE4; break;
        default:
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_RXNCOFTW_INVNCO, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Write to FTW - NCO 1*/
    halError = talSpiWriteByte(device->devHalInfo, spiAddr, (uint8_t)(ncoFtw >> 24));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (spiAddr + 1), (uint8_t)(ncoFtw >> 16));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (spiAddr + 2), (uint8_t)(ncoFtw >> 8));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (spiAddr + 3), (uint8_t)(ncoFtw));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    return retVal;
}

talRecoveryActions_t talSetupNcoShifter(taliseDevice_t *device, taliseInit_t *init)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    int32_t pfirFs_kHz = 0;
    int32_t outFs_kHz = 0;
    int32_t ddcOutFsDiv2_kHz = 0;
    uint32_t nco1FreqUnsigned_kHz = 0;
    uint64_t nco1Ftw = 0;
    uint32_t nco2FreqUnsigned_kHz = 0;
    uint64_t nco2Ftw = 0;
    int32_t inputCenterFreq_kHz = 0;
    int32_t nco1OutputCenterFreq_khz = 0;
    int32_t nco2OutputCenterFreq_khz = 0;
    int32_t bandWidthDiv2 = 0;
    uint8_t ddcHbEnabled = 0;
    int32_t ddcHbCorner_kHz = 0;
    int32_t pfirCorner_kHz = 0;
    uint8_t ncoUpdateFtw = 0;

    static const uint64_t POW_2_32 = ((uint64_t)1) << 32;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "talRecoveryActions_t()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    bandWidthDiv2 = init->rx.rxProfile.rxNcoShifterCfg.bandAInputBandWidth_kHz >> 1;

    inputCenterFreq_kHz = init->rx.rxProfile.rxNcoShifterCfg.bandAInputCenterFreq_kHz;
    nco1OutputCenterFreq_khz = inputCenterFreq_kHz + init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz;
    nco2OutputCenterFreq_khz = nco1OutputCenterFreq_khz + init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz;

    /* scale the pfirFs for the selected DDC mode */
    /* Fs at output of PFIR : Twice output rate due to decimation in DDC */
    if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2) ||
        (init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF))
    {
        pfirFs_kHz = device->devStateInfo.rxOutputRate_kHz << 1;
        ddcHbEnabled = 1;

        /* DDC HB corner is at 0.4 * rx output rate.  0.4 = 2/5 */
        ddcHbCorner_kHz = (int32_t)(device->devStateInfo.rxOutputRate_kHz << 1) / 5;
    }
    else if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2) ||
             (init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF))
    {
        pfirFs_kHz = device->devStateInfo.rxOutputRate_kHz >> 1;
        ddcHbEnabled = 1;

        /* DDC HB corner is at 0.4 * (rx output rate/2).  0.4 = 2/5 */
        ddcHbCorner_kHz = (int32_t)(device->devStateInfo.rxOutputRate_kHz) / 5;
    }
    else if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY) ||
             (init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF))
    {
        pfirFs_kHz = device->devStateInfo.rxOutputRate_kHz;
        ddcHbEnabled = 1;

        /* DDC HB corner is at 0.4 * (rx output rate/2).  0.4 = 2/5 */
        ddcHbCorner_kHz = (int32_t)(device->devStateInfo.rxOutputRate_kHz) / 5;
    }
    else if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS) ||
             (init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
    {
        pfirFs_kHz = device->devStateInfo.rxOutputRate_kHz;
        ddcHbEnabled = 0;

        /* DDC HB corner is at the Pfir corner since HalfBand is disabled */
        ddcHbCorner_kHz = (int32_t)((init->rx.rxProfile.rfBandwidth_Hz / 1000) >> 1);;
    }

    outFs_kHz = device->devStateInfo.rxOutputRate_kHz;
    ddcOutFsDiv2_kHz = (outFs_kHz >> 1);

    pfirCorner_kHz = ((init->rx.rxProfile.rfBandwidth_Hz / 1000) >> 1);


    /* Range check that signal passband edges are within Rx PFIR corners */
    if (((inputCenterFreq_kHz + bandWidthDiv2) > pfirCorner_kHz) ||
        ((inputCenterFreq_kHz - bandWidthDiv2) < -pfirCorner_kHz))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETUPNCOSHIFTER_INV_PFIR_CORNER, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* If DDC HB enabled, verify that input signal after possible NCO1 shift is in passband of DDC HB */
    if (ddcHbEnabled > 0)
    {
        if (((nco1OutputCenterFreq_khz + bandWidthDiv2) > ddcHbCorner_kHz) ||
            ((nco1OutputCenterFreq_khz - bandWidthDiv2) < -ddcHbCorner_kHz))
        {
             return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETUPNCOSHIFTER_INV_DDCHB_CORNER, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }

    /* Range check NCO2 shifted output is within -Fs/2 to Fs/2 of Rx output rate */
    if (((nco2OutputCenterFreq_khz + bandWidthDiv2) > ddcOutFsDiv2_kHz) ||
        ((nco2OutputCenterFreq_khz - bandWidthDiv2) < -ddcOutFsDiv2_kHz))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETUPNCOSHIFTER_INV_NCO2SHIFT, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* if nco1 shift */
    if (init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz != 0)
    {
        /* Convert from -ve frequencies to their positive equivalents */
        nco1FreqUnsigned_kHz = (init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz >= 0)
                ? init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz
                : (pfirFs_kHz + init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz) ;

        /* Convert positive frequencies to their FTW equivalents */
        nco1Ftw = ((((uint64_t)nco1FreqUnsigned_kHz * POW_2_32) << 1) + pfirFs_kHz) / (pfirFs_kHz << 1); /* integer rounding */

        /* Check FTW is not more than 32 bits */
        if (nco1Ftw >= POW_2_32)
        {
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETUPNCOSHIFTER_FTW_OVRG, retVal, TALACT_ERR_CHECK_PARAM);
        }

        retVal = talSetRxNcoFtw(device, TAL_RX1_NCO1A, (uint32_t)nco1Ftw);
        IF_ERR_RETURN(retVal);

        retVal = talSetRxNcoFtw(device, TAL_RX2_NCO1A, (uint32_t)nco1Ftw);
        IF_ERR_RETURN(retVal);

        /* Update FTW words - write at bottom of function */
        ncoUpdateFtw |= 0x11;
    }

    /* if nco2 shift */
    if (init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz != 0)
    {
        /* Convert from -ve frequencies to their positive equivalents */

        nco2FreqUnsigned_kHz = (init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz >= 0)
                ? init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz
                : (outFs_kHz + init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz);

        /* Convert positive frequencies to their FTW equivalents */
        nco2Ftw = ((((uint64_t)nco2FreqUnsigned_kHz * POW_2_32) << 1) + outFs_kHz) / (outFs_kHz << 1); /* integer rounding */

        /* Check FTW is not more than 32 bits */
        if (nco2Ftw >= POW_2_32)
        {
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETUPNCOSHIFTER_FTW_OVRG, retVal, TALACT_ERR_CHECK_PARAM);
        }

        retVal = talSetRxNcoFtw(device, TAL_RX1_NCO2A, (uint32_t)nco2Ftw);
        IF_ERR_RETURN(retVal);

        retVal = talSetRxNcoFtw(device, TAL_RX2_NCO2A, (uint32_t)nco2Ftw);
        IF_ERR_RETURN(retVal);

        /* Update NCO2 FTW words */
        ncoUpdateFtw |= 0x44;
    }

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_NCO_FTW_UPDATE_CONTROL, ncoUpdateFtw);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    return retVal;
}

uint32_t TALISE_programDualBandLnaGainTable( taliseDevice_t *device, taliseDualBandLnaGainTable_t *gainTablePtr, uint8_t numGainIndexesInTable, taliseRxChannels_t rxChannel)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t registerValue = 0;
    uint8_t gtConfigReg = 0;
    uint8_t count = 0;

    static const uint8_t MAX_LNA_GAIN_TABLE_ENTRIES = 4;
    static const uint8_t EN_TABLECLK = 0x05;
    static const uint8_t EN_WRSTB = 0x02;

    if ((rxChannel == TAL_RX1) ||
        (rxChannel == TAL_RX2) ||
        (rxChannel == TAL_RX1RX2))
    {
        /* Verify Rx profile is valid before allowing to set the Rx gain table, this
         * ensures the device->rx structure pointers are valid
         */
        if ((device->devStateInfo.profilesValid  & RX_PROFILE_VALID) == 0)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_DUALBAND_LNA_TABLE_INV_PROFILE, retVal, TALACT_ERR_CHECK_PARAM);
        }

        /* Check for proper mapping for gain table and passed table number of indexes */
        if ((numGainIndexesInTable > MAX_LNA_GAIN_TABLE_ENTRIES) ||
            (numGainIndexesInTable == 0))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_DUALBAND_LNA_TABLE_INV_INDEX, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_DUALBAND_LNA_TABLE_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (gainTablePtr == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_DUALBAND_LNA_TABLE_NULL_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* starting the gain table clock and read from gain table address bits */
    gtConfigReg = ((uint8_t)rxChannel << 3) | EN_TABLECLK;
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, gtConfigReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* The write strobe to gain table configuration register */
    gtConfigReg |= EN_WRSTB;

    /* Load gain table */
    for (count = 0; count < numGainIndexesInTable; count ++)
    {
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_WORD_ADDRESS, count);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN(retVal);

        registerValue = ((gainTablePtr[count].dualbandGain & 0x3F) << 2) | (gainTablePtr[count].dualbandControl & 0x03);
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_WORD_DATA_DUALBAND, registerValue);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN(retVal);

        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, gtConfigReg);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN(retVal);
    }

    /* disabling the gain table clock */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_TABLE_CONFIGURATION, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Set Max LNA indices in Rx1 AGC to match the number of gain table indices */
    if ((rxChannel == TAL_RX1) ||
        (rxChannel == TAL_RX1RX2))
    {
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX1_SLOWLOOP_CONFIG, (uint8_t)(numGainIndexesInTable-1));
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN(retVal);
    }

    /* Set Max LNA indices in Rx2 AGC to match the number of gain table indices */
    if ((rxChannel == TAL_RX2) ||
        (rxChannel == TAL_RX1RX2))
    {
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX2_SLOWLOOP_CONFIG, (uint8_t)(numGainIndexesInTable-1));
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN(retVal);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_setGainTableExtCtrlPins(taliseDevice_t *device, taliseRxChannels_t rxChannel, uint8_t enable3p3vGpios)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t curr3p3SrcCtrl = 0x00;
    uint16_t currGpio3p3Oe = 0;
    uint16_t usedGpio3p3pins = 0;
    uint16_t gpio3p3FreeMask = 0;
    uint16_t gpio3p3UsedMask = 0;
    static const uint8_t GPIO3P3_RX1_EXT_CTRL_WORD_EN = 0x04;
    static const uint8_t GPIO3P3_RX2_EXT_CTRL_WORD_EN = 0x40;
    static const uint8_t GPIO3P3_RX1_EXT_CTRL_WORD_OE = 0x0F;
    static const uint8_t GPIO3P3_RX2_EXT_CTRL_WORD_OE = 0xF0;
    static const uint8_t GPIO3P3_LOWERBYTE_LOWERNIBBLE_SRCCTRL_MASK = 0x0F;
    static const uint8_t GPIO3P3_LOWERBYTE_UPPERNIBBLE_SRCCTRL_MASK = 0xF0;
    static const uint8_t ENABLE_EXT_CTRL_WORD_GPIOS = 0x01;
    static const uint32_t SWTEST_SIMULATE_RX1_GPIO3P3_INP = 0x01;
    static const uint32_t SWTEST_SIMULATE_RX2_GPIO3P3_INP = 0x02;

    /*Ensure that the requested channel is valid*/
    if ((rxChannel != TAL_RX1) && (rxChannel != TAL_RX2) && (rxChannel != TAL_RX1RX2))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_INV_CHANNEL,
                                          retVal, TALACT_ERR_CHECK_PARAM);
    }

    /*Ensure that if channel Rx1 is requested, it is initialized*/
    if (((((uint8_t)rxChannel & (uint8_t)TAL_RX1) == (uint8_t)TAL_RX1) &&
       ((device->devStateInfo.initializedChannels & (uint8_t)TAL_RX1) != (uint8_t)TAL_RX1)))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_UNINITIALIZED_RX1,
                                          retVal, TALACT_ERR_CHECK_PARAM);
    }

    /*Ensure that if channel Rx2 is requested, it is initialized*/
    if (((((uint8_t)rxChannel & (uint8_t)TAL_RX2) == (uint8_t)TAL_RX2) &&
       ((device->devStateInfo.initializedChannels & (uint8_t)TAL_RX2) != (uint8_t)TAL_RX2)))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_UNINITIALIZED_RX2,
                                          retVal, TALACT_ERR_CHECK_PARAM);
    }

    /*Verify that the GPIO pins requested are not already in use*/

    /* Read current configuration of GPIO 3.3s */
    halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_GPIO_3P3V_LOWER_BYTE_SOURCE_CONTROL, &curr3p3SrcCtrl);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    retVal = (talRecoveryActions_t)TALISE_getGpio3v3Oe(device, &currGpio3p3Oe);
    IF_ERR_RETURN(retVal);

    usedGpio3p3pins = device->devStateInfo.usedGpio3p3pins;

    if(device->devStateInfo.swTest == SWTEST_SIMULATE_RX1_GPIO3P3_INP)
    {
        curr3p3SrcCtrl = 0;
        usedGpio3p3pins |= 0x01;
    }

    if(device->devStateInfo.swTest == SWTEST_SIMULATE_RX2_GPIO3P3_INP)
    {
        curr3p3SrcCtrl = 0;
        usedGpio3p3pins |= (0x01 << 4);
    }

    /*Check that if
     * Channel requested for Ext Ctrl Word GPIO output is Rx1
     * GPIO 3p3 [3:0] pins are already in use
     * GPIO 3p3 [3:0] pins are not used by this feature
     * then throw an exception
     * */
    if ((((uint8_t)rxChannel & (uint8_t)TAL_RX1) == (uint8_t)TAL_RX1) &&
       ((currGpio3p3Oe & GPIO3P3_RX1_EXT_CTRL_WORD_OE) == GPIO3P3_RX1_EXT_CTRL_WORD_OE) &&
       ((curr3p3SrcCtrl & GPIO3P3_LOWERBYTE_LOWERNIBBLE_SRCCTRL_MASK) != GPIO3P3_RX1_EXT_CTRL_WORD_EN))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_GPIO_IN_USE_RX1,
                                retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((((uint8_t)rxChannel & (uint8_t)TAL_RX1) == (uint8_t)TAL_RX1) &&
       ((usedGpio3p3pins & GPIO3P3_RX1_EXT_CTRL_WORD_OE) != 0) &&
       ((curr3p3SrcCtrl & GPIO3P3_LOWERBYTE_LOWERNIBBLE_SRCCTRL_MASK) != GPIO3P3_RX1_EXT_CTRL_WORD_EN))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_GPIO_IN_USE_RX1,
                                retVal, TALACT_ERR_CHECK_PARAM);
    }

    /*Check that if
     * Channel requested for Ext Ctrl Word GPIO output is Rx2
     * GPIO 3p3 [7:4] pins are already in use
     * GPIO 3p3 [7:4] pins are not used by this feature
     * then throw an exception
     * */
    if ((((uint8_t)rxChannel & (uint8_t)TAL_RX2) == (uint8_t)TAL_RX2) &&
       ((currGpio3p3Oe & GPIO3P3_RX2_EXT_CTRL_WORD_OE) == GPIO3P3_RX2_EXT_CTRL_WORD_OE) &&
       ((curr3p3SrcCtrl & GPIO3P3_LOWERBYTE_UPPERNIBBLE_SRCCTRL_MASK) != GPIO3P3_RX2_EXT_CTRL_WORD_EN))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_GPIO_IN_USE_RX2,
                                retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((((uint8_t)rxChannel & (uint8_t)TAL_RX2) == (uint8_t)TAL_RX2) &&
       ((usedGpio3p3pins & GPIO3P3_RX2_EXT_CTRL_WORD_OE) != 0) &&
       ((curr3p3SrcCtrl & GPIO3P3_LOWERBYTE_UPPERNIBBLE_SRCCTRL_MASK) != GPIO3P3_RX2_EXT_CTRL_WORD_EN))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SETEXTWORDCTRLGPIO_GPIO_IN_USE_RX2,
                                retVal, TALACT_ERR_CHECK_PARAM);
    }

    /*Clear current GPIO configuration and setup again if enable requested*/
    if ((rxChannel == TAL_RX1) || (rxChannel == TAL_RX1RX2))
    {
        /* Free GPIO3P3[3:0] if used */
        gpio3p3FreeMask |= GPIO3P3_RX1_EXT_CTRL_WORD_OE;
        curr3p3SrcCtrl &= ~GPIO3P3_LOWERBYTE_LOWERNIBBLE_SRCCTRL_MASK;

        if (enable3p3vGpios >= ENABLE_EXT_CTRL_WORD_GPIOS)
        {
            /* Enable GPIO3P3[3:0] if requested */
            gpio3p3UsedMask |= GPIO3P3_RX1_EXT_CTRL_WORD_OE;
            curr3p3SrcCtrl |= GPIO3P3_RX1_EXT_CTRL_WORD_EN;
        }
    }

    if ((rxChannel == TAL_RX2) || (rxChannel == TAL_RX1RX2))
    {
        /* Free GPIO3P3[7:4] if used */
        gpio3p3FreeMask |= GPIO3P3_RX2_EXT_CTRL_WORD_OE;
        curr3p3SrcCtrl &= ~GPIO3P3_LOWERBYTE_UPPERNIBBLE_SRCCTRL_MASK;

        if (enable3p3vGpios >= ENABLE_EXT_CTRL_WORD_GPIOS)
        {
            /* Enable GPIO3P3[7:4] if requested */
            gpio3p3UsedMask |= GPIO3P3_RX2_EXT_CTRL_WORD_OE;
            curr3p3SrcCtrl |= GPIO3P3_RX2_EXT_CTRL_WORD_EN;
        }
    }

    usedGpio3p3pins = device->devStateInfo.usedGpio3p3pins & ~gpio3p3FreeMask;
    usedGpio3p3pins |= gpio3p3UsedMask;

    /*Update the Source Control Register*/
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GPIO_3P3V_LOWER_BYTE_SOURCE_CONTROL, curr3p3SrcCtrl);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Set GPIO input enables */
    /* - Set OE for all freed GPIO3p3's to 0 (input) */
    /* - Set OE for all used GPIO3p3's to 1 (output) */
    retVal = (talRecoveryActions_t)TALISE_setGpio3v3Oe(device, gpio3p3UsedMask, (gpio3p3UsedMask | gpio3p3FreeMask));
    IF_ERR_RETURN(retVal);

    /* Update used and freed GPIO's */
    device->devStateInfo.usedGpio3p3pins = usedGpio3p3pins;

    return (uint32_t)retVal;
}

uint32_t TALISE_getRxDecPower(taliseDevice_t *device, taliseRxChannels_t rxChannel, uint16_t *rxDecPower_mdBFS)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t decPowerAddr = 0;
    uint8_t rxDecPower_dBFS = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getRxDecPower()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* null pointer check */
    if (rxDecPower_mdBFS == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
            TAL_ERR_INV_RX_DEC_POWER_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }
    
    if (rxChannel == TAL_RX1)
    {
        decPowerAddr = TALISE_ADDR_DEC_POWER_CH1;
    }
    else if (rxChannel == TAL_RX2)
    {
        decPowerAddr = TALISE_ADDR_DEC_POWER_CH2;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
            TAL_ERR_GETRXDECPOWER_INV_CHANNEL, retVal, TALACT_ERR_CHECK_PARAM);
    }
    
    /* Check that rx profile is valid in current config */
    if (((device->devStateInfo.profilesValid & RX_PROFILE_VALID) == 0)
        || (device->devStateInfo.initializedChannels & (uint32_t)rxChannel) == 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
            TAL_ERR_GETRXDECPOWER_INV_PROFILE, retVal, TALACT_ERR_CHECK_PARAM);
    }
    
    /* Write some value to generate a strobe to latch the value */
    halError = talSpiWriteByte(device->devHalInfo, decPowerAddr, 0x01);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);
    
    /* Read Rx1 Dec Power register */
    halError = talSpiReadByte(device->devHalInfo, decPowerAddr, &rxDecPower_dBFS);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);
    
    *rxDecPower_mdBFS = ((uint16_t)rxDecPower_dBFS) * 250; /* 250 = 1000 * 0.25dB */
    
    return (uint32_t)retVal;
}